package com.example.netcomponent.net;

import android.text.TextUtils;

import com.example.netcomponent.BuildConfig;
import com.example.netcomponent.net.download.DownloadInterceptor;
import com.example.netcomponent.net.utils.LogUtils;
import com.example.netcomponent.net.utils.SpUtils;
import com.trello.rxlifecycle.ActivityEvent;

import java.io.IOException;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by zengxianghui900 on 17/9/30.
 * 网络请求管理类，全局单例
 */

public class HttpManager {

    private volatile static HttpManager INSTANCE;
    //私有构造
    private HttpManager(){}
    //提供访问的公共方法
    public static HttpManager getInstance(){
        if (INSTANCE == null){
            synchronized (HttpManager.class){
                INSTANCE = new HttpManager();
            }
        }
        return INSTANCE;
    }

    /**
     * 执行网络请求
     * @param baseApi 封装好的数据对象
     */
    public void doHttp(final BaseApi baseApi){
        //创建一个okhttpClient builder对象
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //设置请求超时时间
        builder.connectTimeout(baseApi.getConnectionTime(), TimeUnit.SECONDS)
        .readTimeout(baseApi.getConnectionTime(),TimeUnit.SECONDS)
        .writeTimeout(baseApi.getConnectionTime(), TimeUnit.SECONDS);
        //设置日志打印
        builder.addInterceptor(getHttpLoggingInterceptor());
        //添加返回对请求返回响应码的拦截
        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Response response = chain.proceed(chain.request());
                if (response.code() == 302) {
                    //TODO: 表示登录过期跳转到相应的登录验证页面(这个code,可以后台定义，这边可以拦截响应码)
//                    Intent intent = new Intent(baseApi.getRxAppCompatActivity(), FaceLoginActivity.class);
//                    baseApi.getRxAppCompatActivity().startActivity(intent);
                }
                return response;
            }
        });
        //添加读取token的interceptor
        builder.addInterceptor(new ReadTookenInterceptor(baseApi));
//        builder.addInterceptor(new SaveCookiesInterceptor(baseApi));

        ProgressSubscriber subscriber = new ProgressSubscriber(baseApi);

        //添加进度回调
        if(baseApi.isShowProgress()){
            //设置进度回调拦截
            builder.addInterceptor(new DownloadInterceptor(subscriber));
        }
        //创建retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())    //添加定义好的OkHttpClient
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(getBaseUrl())
                .build();

        Observable observable = baseApi.getObservable(retrofit)
                /*失败后的retry配置*/
                .retryWhen(new RetryWhenNetworkException(baseApi.getRetryCount(),
                        baseApi.getRetryDelay(), baseApi.getRetryIncreaseDelay()))
                /*生命周期管理*/
//                .compose(basePar.getRxAppCompatActivity().bindToLifecycle())
                .compose(baseApi.getRxAppCompatActivity().bindUntilEvent(ActivityEvent.DESTROY))
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread())
                /*结果判断*/
                .map(baseApi);


        /*链接式对象返回,后面扩展需要*/
//        HttpOnNextListener httpOnNextListener = baseApi.getListener();
//        if (httpOnNextListener != null) {
//            httpOnNextListener.onNext(baseApi);
//        }

        /*数据回调*/
        observable.subscribe(subscriber);

    }

    /**
     * 获取基础网址（所有请求地址前面相同的部分）
     * 根据是否是debug包自动配置
     * @return
     */
    private String getBaseUrl() {
        return CommonApiService.BASE_URL;
    }


    /**
     * 日志输出
     * 自行判定是否添加
     * @return
     */
    private HttpLoggingInterceptor getHttpLoggingInterceptor(){
        //日志显示级别
        HttpLoggingInterceptor.Level level= HttpLoggingInterceptor.Level.BASIC;
        if (BuildConfig.DEBUG){
            level= HttpLoggingInterceptor.Level.BODY;
        }

        //新建log拦截器
        HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
               LogUtils.e("Retrofit====Message:"+message);
               LogUtils.saveLogToSD(LogUtils.INTERFACE_MODULE,"Retrofit====Message:"+message);
            }
        });
        loggingInterceptor.setLevel(level);
        return loggingInterceptor;
    }

    /**
     * 添加token的拦截器
     * @return
     */
    public class ReadTookenInterceptor implements Interceptor {
        private BaseApi mBaseApi;
        public ReadTookenInterceptor(BaseApi baseApi) {
           this.mBaseApi = baseApi;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request.Builder builder = chain.request().newBuilder();

            String token = SpUtils.getStringValue(mBaseApi.getRxAppCompatActivity(), AppConstant.SpKey.TOKEN);
            //登录的时候不需要添加请求头
            if (mBaseApi.isNeedToken() && !TextUtils.isEmpty(token)) {
                builder.addHeader("token", token);
                LogUtils.e("OkHttp", "Adding Header: " + token); // This is done so I know which headers are being added; this interceptor is used after the normal logging of OkHttp
            }
            return chain.proceed(builder.build());
        }
    }


    /**
     * 保存cookie的拦截器
     */
    public class SaveCookiesInterceptor implements Interceptor {
        private BaseApi mBaseApi;
        public SaveCookiesInterceptor(BaseApi baseApi) {
            this.mBaseApi = baseApi;
        }
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response originalResponse = chain.proceed(chain.request());
            //只有登录时，才去保存cookie
            if (!mBaseApi.isNeedToken() && !originalResponse.headers("Set-Cookie").isEmpty()) {
                HashSet<String> cookies = new HashSet<>();
                for (String header : originalResponse.headers("Set-Cookie")) {
                    cookies.add(header);
                }
                SpUtils.putSetValue(mBaseApi.getRxAppCompatActivity(), AppConstant.SpKey.TOKEN,cookies);
            }

            return originalResponse;
        }
    }

}
